package d1_thread_code;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class ThreadDemo03 {
    public static void main(String[] args) {
        //目标: 掌握多线程的创建方式三: 可以返回线程执行完毕后的结果
        //3、创建Callable对象
        //  注意这个泛型也是要写的,代表结果返回值的类型
        Callable<String> call = new MyCallable(100);//多态写法
        //4、把Callable对象, 封装成FutureTask对象
        // 未来任务对象有两个作用:
        //          它是一个Runnable对象
        //          它可以获取线程执行后的结果
        // Runnable task = new FutureTask<>(call);--->并没有报错
        FutureTask<String> task = new FutureTask<>(call);
        //5、把未来任务对象交给线程对象
        Thread t = new Thread(task);
        //6、启动线程
        t.start();

        //第二个子线程

        Callable<String> call1 = new MyCallable(100);//多态写法
        FutureTask<String> task1 = new FutureTask<>(call);
        Thread t2 = new Thread(task);
        t2.start();
        //最后调用FutureTask对象的get方法进行获取结果
        try {
            //如果第一个线程没有执行完毕, 会在这里等待第一个线程执行完毕, 再取结果()
            //解释:主线程一路执行下来,可能出现子线程没有执行完,就获取结果,底层会帮我们维护,不用担心
            String s = task.get();//获取第一个子线程的结果
            //进行打印操作
            System.out.println("子线程1的结果" + s);
        } catch (Exception e) {
            e.printStackTrace();//打印堆栈的信息
        }

        try {
            String s = task1.get();
            //展示结果
            System.out.println("子线程2的结果" + s);
        } catch (Exception e) {
            e.printStackTrace();//打印堆栈的信息
        }

    }
}

//1、定义一个类实现Callable接口
//                                这个泛型代表结果要返回的数据类型
//                                      ↓
class MyCallable implements Callable<String> {
    private int n;

    public MyCallable(int n) {
        this.n = n;
    }

    //2、重写call方法, 声明任务和返回的结果
    @Override
    public String call() throws Exception {
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += i;
        }
        return "子线程求和1-" + n + "结果:" + sum;
    }
}